package cn.jetpiece.cloud.core.filters;

import cn.jetpiece.cloud.config.properties.JetpieceGatewayProperties;
import cn.jetpiece.cloud.core.consts.GatewayConstants;
import cn.jetpiece.cloud.core.consts.GatewayFilterOrdered;
import cn.jetpiece.cloud.core.util.AuthenticationUtils;
import cn.jetpiece.cloud.core.util.IpInfoUtils;
import cn.jetpiece.cloud.model.contants.CommonConstant;
import cn.jetpiece.cloud.resource.annotation.keys.ResourceKey;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.route.Route;
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
import org.springframework.core.Ordered;
import org.springframework.http.HttpMethod;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.UUID;

/**
 * 请求号过滤器(全局过滤器)
 * 请求添加请求好
 *
 * @author XuJZ
 */
@Component
public class RequestNoFilter implements GlobalFilter, Ordered {


    @Override
    public int getOrder() {
        return GatewayFilterOrdered.REQUEST_NO_ORDER;
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //生成唯一请求号uuid
        String requestNo = UUID.randomUUID().toString();
        //增加请求头中的请求号
        ServerHttpRequest request = exchange.getRequest();
        String ipAddress = IpInfoUtils.getIpAddr(request);

        Route route = (Route) exchange.getAttributes().get(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
        String path = request.getPath().toString();
        String resourcePath = path;

        boolean ignore;
        if (path.endsWith("/api-docs") && JetpieceGatewayProperties.getInstance().getDoc()) {
            path = path.substring(path.indexOf("/", 1));
            ignore = true;
        } else {
            ignore = AuthenticationUtils.urlIgnore(route.getId(), path);
        }

        ServerHttpRequest.Builder builder = request.mutate();
        /* 获取HttpMethod */
        HttpMethod httpMethod = getHttpMethod(request);

        builder.path(path)
                .header(CommonConstant.REQUEST_NO_HEADER_NAME, requestNo)
                .method(httpMethod)
                /* 设置网关基础Url */
                .header(CommonConstant.GATEWAY_BASE_PATH, AuthenticationUtils.getGatewayBaseUrl(exchange))
                /* 设置Token */
                .header(GatewayConstants.AUTH_HEADER, AuthenticationUtils.getToken(request))
                /* 设置IP */
                .header(GatewayConstants.REAL_IP, ipAddress)
                /* 设置后端服务编码 */
                .header(ResourceKey.REQUEST_SERVER_CODE, route.getId());

        if (ignore) {
            /* 忽略的url */
            builder.header(GatewayConstants.IGNORE_URL, "1");
        } else {
            /* 获取请求资源Key */
            resourcePath = AuthenticationUtils.getResourceKey(route.getUri().getHost(), httpMethod.name() + ResourceKey.RES_METHOD_URL_SEPARATOR + path);

        }
        /* 设置资源Key到Header */
        builder.header(ResourceKey.REQUEST_RESOURCE_KEY, resourcePath);
        request = builder.build();

        //增加响应头的请求号
        ServerHttpResponse response = exchange.getResponse();
        return chain.filter(exchange.mutate().request(request).response(response).build());
    }

    /**
     * 获取HttpMethod
     *
     * @param request 请求
     * @return HttpMethod
     */
    private HttpMethod getHttpMethod(ServerHttpRequest request) {
        /* HttpMethod转发 */
        String overrideMethod = request.getHeaders().getFirst(GatewayConstants.X_HTTP_METHOD_OVERRIDE);
        HttpMethod httpMethod = null;
        if (overrideMethod != null) {
            httpMethod = HttpMethod.resolve(overrideMethod.toUpperCase());
        }
        if (httpMethod == null) {
            return request.getMethod();
        }
        return httpMethod;
    }

}
